<!--
  Test out tracking and prediction quality. This test outputs the magnitude of
  angular velocity of adjacent head track quaternions in 3 confifgurations:

  1. No prediction
  2. Interpolation
  3. Full prediction (w/ variable future time).
-->
<head>
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
  overflow: hidden;
  padding: 0; margin: 0;
}
</style>
</head>

<body></body>

<script src="../bower_components/dat.gui/dat.gui.js"></script>

<script src="../js/deps/webvr-polyfill.js"></script>
<script src="../js/deps/three.js"></script>
<script src="../js/deps/VRControls.js"></script>
<script src="../js/deps/VREffect.js"></script>
<script src="../build/webvr-manager.js"></script>

<script>
var TrackingParams = function() {
  this.trackingMode = 'predict';
  this.predictionTime = 50;
  //this.renderMode = 'brightness';
};

window.onload = function() {
  var text = new TrackingParams();
  var gui = new dat.GUI();
  var modeChanged = gui.add(text, 'trackingMode',
      ['none', 'interpolate', 'predict'] );
  var timeChanged = gui.add(text, 'predictionTime', 0, 200);
  //var renderMode = gui.add(text, 'renderMode', ['brightness', 'scene']);

  modeChanged.onFinishChange(onModeChanged);
  timeChanged.onFinishChange(onTimeChanged);
};

function onModeChanged(value) {
  WEBVR_PREDICTION_MODE = value;
}

function onTimeChanged(value) {
  WEBVR_PREDICTION_TIME_MS = value;
}

var renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);

// Append the canvas element created by the renderer to document body element.
document.body.appendChild(renderer.domElement);

// Create a three.js scene.
var scene = new THREE.Scene();

// Create a three.js camera.
var dummyCamera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.3, 10000);

var camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);

// Apply VR headset positional data to camera.
var controls = new THREE.VRControls(dummyCamera);

// Apply VR stereo rendering to renderer.
var effect = new THREE.VREffect(renderer);
effect.setSize(window.innerWidth, window.innerHeight);

// Create a VR manager helper to enter and exit VR mode.
var manager = new WebVRManager(renderer, effect, {hideButton: false});

var canvas = document.createElement('canvas');
canvas.width = 64;
canvas.height = 64;
var ctx = canvas.getContext('2d');

// Turn canvas into texture.
var texture = new THREE.Texture(canvas);
texture.needsUpdate = true;

var geometry = new THREE.PlaneGeometry(2, 2);
var material = new THREE.MeshBasicMaterial({
  map: texture,
  //color: 0x333333,
  side: THREE.FrontSide
});

var test = new THREE.Mesh(geometry, material);
test.position.z = -1;
scene.add(test);

var inputDevice = null;
manager.getDeviceByType_(PositionSensorVRDevice).then(function(dev) {
  inputDevice = dev;
});

var last = new THREE.Quaternion();
var delta = new THREE.Quaternion();
var MAX_ANGULAR_SPEED = 0.3;
function animate(timestamp) {
  // Update VR headset position and apply to camera.
  controls.update();

  // Render the scene through the manager.
  manager.render(scene, camera, timestamp);

  if (window.inputDevice) {
    var current = inputDevice.getState().orientation;
    // Calculate angular distance between current and last positions.
    if (window.last) {
      // Get |angular velocity| between current and last.
      delta.copy(last);
      delta.inverse();
      delta.multiply(current);
      var angle = getAngle(delta);

      // Convert to percent.
      var percent = angle / MAX_ANGULAR_SPEED;
      setColor(percent);

      // Save this position.
      last.copy(current);
    }
  }

  requestAnimationFrame(animate);
}

function setColor(percent) {
  var v = Math.round(percent * 255);
  var style = 'rgb(' + v + ',' + v + ',' + v + ')';
  ctx.fillStyle = style;
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  texture.needsUpdate = true;
};

function getAngle(quat) {
  // angle = 2 * acos(qw)
  // If w is greater than 1 (THREE.js, how can this be?), arccos is not defined.
  if (quat.w > 1) {
    return 0;
  }
  var angle = 2 * Math.acos(quat.w);
  // Normalize the angle to be in [-π, π].
  if (angle > Math.PI) {
    angle -= 2 * Math.PI;
  }
  return angle;
}

function onWindowResize() {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();

  effect.setSize(window.innerWidth, window.innerHeight);
}

window.addEventListener('resize', onWindowResize, false);


// Kick off animation loop
animate();

</script>
